This is a classic microservices pain point. Opening 12 terminals and typing `npm run dev` 12 times is annoying.

Here are **3 Levels of Automation** we can add to CWM to solve this, ranging from "Quick Fix" to "Professional Workspace Management."

-----

### 1\. Level 1: The "Batch Execute" Flag (Quickest)

We add an `--exec` (or `-x`) flag to `cwm jump`.
This allows you to jump to multiple projects *and* run a specific command in all of them instantly.

**Usage:**

```bash
# Opens terminal for projects 1, 2, and 3 and runs "npm run dev" in all of them
cwm jump 1,2,3 --terminal --exec "npm run dev"
```

**Pros:** Easy to implement. Good if all projects use the same command.
**Cons:** You still have to type the IDs every time.

-----

### 2\. Level 2: The "Startup Command" Config (Persistent)

We update `projects.json` so each project remembers its own startup command.

  * Project A (Node): `"startup": "npm run dev"`
  * Project B (Python): `"startup": "venv/Scripts/activate && python main.py"`

**Usage:**

```bash
cwm project config --id 1 --startup "npm run dev"
cwm jump 1 --terminal  # Automatically runs the startup command
```

**Pros:** You set it once and forget it.
**Cons:** You still have to select the projects manually.

-----

### 3\. Level 3: "Workspaces / Groups" (The Ultimate Solution) 🏆

This is the best solution for your 12-project scenario. We create "Groups".

**How it works:**

1.  You define a group named `microservices`.
2.  You add your 12 projects to this group.
3.  You run **one command**:
    ```bash
    cwm group start microservices
    ```
4.  **Result:** CWM explodes into action, opening 12 separate terminal windows (or tabs), automatically navigating to the correct folders, and running the specific start command for each one.

-----

### 🚀 Implementation Plan (Level 1 & 2 Combined)

Let's implement the **`--exec` flag** logic right now in `jump_cmd.py`. This is the foundation for everything else.

We need to modify `_launch_terminal` to accept a command argument.

#### Critical Logic for Windows (`cmd /k`)

To run a command and **keep the window open** (so you can see the logs), we must use:
`start cmd /k "cd /d {path} && {command}"`

  * `/k`: Executes the command and **remains** (Keep).
  * `/c`: Executes and **closes** (Close).

### Code Update: `src/cwm/jump_cmd.py`

Here is the updated code that supports running commands.

```python
# src/cwm/jump_cmd.py
import click
import subprocess
import os
import shutil
import shlex
from .storage_manager import StorageManager
from difflib import get_close_matches

# ... (_launch_editor and _resolve_project remain unchanged) ...

def _launch_terminal(path: str, exec_cmd: str = None):
    """
    Launches a terminal.
    If exec_cmd is provided, it runs that command inside the new terminal.
    """
    is_windows = os.name == 'nt'
    try:
        if is_windows:
            # Windows Logic
            # We construct a command chain: cd to path AND run user command
            
            if exec_cmd:
                # "start" pops a new window.
                # "cmd /k" runs the command and KEEPS window open.
                # "cd /d" ensures we switch drives if needed.
                # Title is set to the command name for clarity.
                
                final_cmd = f'start "{exec_cmd}" cmd /k "cd /d {path} && {exec_cmd}"'
                subprocess.Popen(final_cmd, shell=True)
                click.echo(f"Running '{exec_cmd}' in new terminal...")
            else:
                # Just open terminal at path
                if shutil.which("wt"):
                    subprocess.Popen(["wt", "-d", path], shell=True)
                else:
                    subprocess.Popen(["start", "cmd", "/k", f"cd /d {path}"], shell=True)
                    
        else:
            # Linux/Mac Logic (Gnome Terminal example)
            if shutil.which("gnome-terminal"):
                if exec_cmd:
                    # -- means "don't process further options", bash -c runs string
                    # ; exec bash keeps the shell open after command finishes
                    full_arg = f"cd {path}; {exec_cmd}; exec bash"
                    subprocess.Popen(["gnome-terminal", "--", "bash", "-c", full_arg])
                else:
                    subprocess.Popen(["gnome-terminal", "--working-directory", path])
            elif shutil.which("open"): # Mac
                # Mac is trickier with 'open', usually requires AppleScript for commands
                # Fallback to basic open
                subprocess.Popen(["open", "-a", "Terminal", path])
                if exec_cmd:
                    click.echo("Warning: Auto-execution on Mac Terminal requires advanced permissions (not implemented yet).")

    except Exception as e:
        click.echo(f"Failed to launch terminal: {e}")


@click.command("jump")
@click.argument("names", required=False)
@click.option("-t", "--terminal", is_flag=True, help="Also open a new terminal window.")
@click.option("-x", "--exec", "exec_cmd", help="Command to run in the terminal (e.g., 'npm run dev').")
@click.option("-l", "--list", "list_mode", is_flag=True, help="Force list mode.")
@click.option("-n", "count", default="10", help="Number of projects to show.")
def jump_cmd(names, terminal, list_mode, count, exec_cmd):
    """
    Jump to projects.
    Use --exec "cmd" to auto-run commands in new terminals.
    """
    manager = StorageManager()
    data = manager.load_projects()
    projects = data.get("projects", [])

    if not projects:
        click.echo("No projects found.")
        return

    # ... (Selection Logic: Same as before) ...
    # ... (Copy the raw_input/tokens/valid_targets logic from previous response) ...
    
    # <--- INSERT SELECTION LOGIC HERE FROM PREVIOUS CODE --->
    # (I'm skipping repeating the list/prompt logic to save space, 
    #  assume valid_targets is populated correctly)
    
    # --- MOCKUP of selection logic for context ---
    raw_input = names
    if list_mode or not names:
        # ... display logic ...
        raw_input = click.prompt("Select IDs/Aliases", default="", show_default=False)
    if not raw_input: return
    
    tokens = raw_input.split(',')
    valid_targets = []
    for token in tokens:
        target = _resolve_project(token, projects)
        if target and target not in valid_targets:
            valid_targets.append(target)
    # ---------------------------------------------

    if not valid_targets:
        click.echo("No valid projects found.")
        return

    click.echo(f"Launching {len(valid_targets)} project(s)...")
    
    for target in valid_targets:
        target["hits"] = target.get("hits", 0) + 1
        
        # 1. Launch Editor (Only if --exec is NOT present, OR if user explicitly wants both)
        # Usually if you run --exec, you just want the terminals, but let's keep editor as default
        # unless you strictly want terminal only. 
        
        # Let's say: If --exec is used, we force terminal mode.
        if exec_cmd:
            _launch_terminal(target["path"], exec_cmd)
        else:
            # Standard Jump behavior
            _launch_editor(target["path"], manager)
            if terminal:
                _launch_terminal(target["path"])

    manager.save_projects(data)
```

### How to use this for your 12 projects right now:

1.  **Identify IDs:** Run `cwm jump` to see your IDs (e.g., 1 to 12).
2.  **The Master Command:**
    ```powershell
    cwm jump 1,2,3,4,5,6,7,8,9,10,11,12 --exec "npm run dev"
    ```

**Result:**
12 independent Command Prompt windows will pop up.
Each one will `cd` into its respective folder.
Each one will run `npm run dev`.
All of them will stay open so you can see the logs.

### Future Step: The "Group" Command

If you like this, the next step is to implement `cwm group add microservices 1,2,3...` so you don't have to type the numbers every time. Would you like to plan that next?